package com.liuym.student.service.impl;

import com.liuym.common.constants.ResponseCodeConstants;
import com.liuym.common.dubbo.student.dto.StudentScoreDTO;
import com.liuym.common.exception.StudentException;
import com.liuym.student.common.LogAndExceptionCommon;
import com.liuym.student.repository.mapper.StudentMapper;
import com.liuym.student.repository.mapper.StudentScoreMapper;
import com.liuym.student.repository.model.bo.StudentScoreBO;
import com.liuym.student.repository.model.bo.StudentScoreBatchBO;
import com.liuym.student.repository.model.entity.StudentScore;
import com.liuym.student.service.StudentScoreService;
import com.liuym.student.service.StudentService;
import com.vip.vjtools.vjkit.mapper.BeanMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Liuym
 * @date 2018/12/10 10:19
 * @describe：
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class StudentScoreServiceImpl implements StudentScoreService {

    @Autowired
    private StudentScoreMapper studentScoreMapper;

    @Autowired
    private StudentService studentService;

    @Autowired
    private StudentMapper studentMapper;

    @Override
    public boolean addStudentScore(String studentScoreTableName, String userName, StudentScoreBO studentScoreBO) throws StudentException {

        baseParamCheck(studentScoreBO, studentMapper.findStudentNumberList());
        studentScoreBO.setOperateDate(new Date());
        studentScoreBO.setOperator(userName);
        StudentScore studentScore = BeanMapper.map(studentScoreBO, StudentScore.class);
        int insertStudentScore = studentScoreMapper.insert(studentScoreTableName, studentScore);
        int updateStudent = studentService.updateScoreByStudentNumber(studentScoreBO.getFinallyScore(), studentScoreBO.getStudentNumber());
        if (insertStudentScore > 0 && updateStudent > 0) {
            return true;
        }
        return false;
    }

    @Override
    public Map<String, Object> addStudentScoreBatch(String studentScoreTableName, String userName, List<StudentScoreBO> studentScoreBOList) throws StudentException {
        Map<String, Object> map = new HashMap<String, Object>();
        List<StudentScore> studentScoreList = new ArrayList<StudentScore>();
        List<StudentScoreDTO> failStudentScoreList = new ArrayList<StudentScoreDTO>();
        int failResult = 0; //验证不通过数量
        List<Long> studentNumberList = studentMapper.findStudentNumberList();
        for (StudentScoreBO studentScoreBO : studentScoreBOList) {
            String checkExcelParam = checkExcelParam(studentScoreBO, studentNumberList);
            if ("验证通过".equals(checkExcelParam)) {
                StudentScore studentScore = BeanMapper.map(studentScoreBO, StudentScore.class);
                studentScoreList.add(studentScore);
            } else {
                failResult++;
                studentScoreBO.setFailReason(checkExcelParam);
                failStudentScoreList.add(BeanMapper.map(studentScoreBO, StudentScoreDTO.class));
            }
        }
        map.put("failResult", failResult);
        map.put("failStudentScore", failStudentScoreList);
        //开始批量存入t_stucent_score表
        if (0 < studentScoreList.size()) {
            //限制每批存储大小
            int limitDataNumber = 200;
            int size = studentScoreList.size();
            List<StudentScoreBatchBO> studentScoreBatchBOList = null;
            if (size < limitDataNumber) {
                studentScoreMapper.addStudentScoreList(studentScoreTableName, studentScoreList);
                studentScoreBatchBOList =
                        studentScoreList
                                .stream()
                                .map(s -> BeanMapper.map(s, StudentScoreBatchBO.class))
                                .collect(Collectors.toList());
                //批量更新t_student的f_score字段
                List<StudentScoreBatchBO> groupClassScore = getGroupClassScore(studentScoreBatchBOList);
                //2.再更新
                studentService.updateScoreByStudentNumberBatch(groupClassScore);
            } else {
                // 分批数
                int part = size / limitDataNumber;
                for (int i = 0; i < part; i++) {
                    List<StudentScore> studentScoreListPart =
                            studentScoreList.subList(0, limitDataNumber);
                    studentScoreMapper.addStudentScoreList(studentScoreTableName, studentScoreListPart);
                    studentScoreBatchBOList =
                            studentScoreListPart
                                    .stream()
                                    .map(s -> BeanMapper.map(s, StudentScoreBatchBO.class))
                                    .collect(Collectors.toList());
                    //批量更新t_student的f_score字段
                    List<StudentScoreBatchBO> groupClassScore = getGroupClassScore(studentScoreBatchBOList);
                    //2.再更新
                    studentService.updateScoreByStudentNumberBatch(groupClassScore);
                    // 剔除
                    studentScoreList.subList(0, limitDataNumber).clear();
                }
                if (!studentScoreList.isEmpty()) {
                    // 存入剩下的
                    studentScoreMapper.addStudentScoreList(studentScoreTableName, studentScoreList);
                    studentScoreBatchBOList =
                            studentScoreList
                                    .stream()
                                    .map(s -> BeanMapper.map(s, StudentScoreBatchBO.class))
                                    .collect(Collectors.toList());
                    //批量更新t_student的f_score字段
                    //1.先分组
                    List<StudentScoreBatchBO> groupClassScore = getGroupClassScore(studentScoreBatchBOList);
                    //2.再更新
                    studentService.updateScoreByStudentNumberBatch(groupClassScore);
                }
            }
        }
        return map;
    }

    private List<StudentScoreBatchBO> getGroupClassScore(List<StudentScoreBatchBO> studentScoreBatchBOList) {
        Map<Long, LongSummaryStatistics> collect = studentScoreBatchBOList.stream().collect(
                Collectors.groupingBy(StudentScoreBatchBO::getStudentNumber,
                        Collectors.summarizingLong(StudentScoreBatchBO::getFinallyScore)));
        studentScoreBatchBOList.clear();
        StudentScoreBatchBO studentScoreBatchBO;
        for (Map.Entry<Long, LongSummaryStatistics> entry : collect.entrySet()) {
            Long key = entry.getKey();
            LongSummaryStatistics finallyScore = entry.getValue();
            studentScoreBatchBO = new StudentScoreBatchBO();
            studentScoreBatchBO.setStudentNumber(key);
            studentScoreBatchBO.setFinallyScore((int) finallyScore.getSum());
            studentScoreBatchBOList.add(studentScoreBatchBO);
        }
        return studentScoreBatchBOList;
    }

    /**
     * 验证excel参数
     *
     * @param studentScoreBO
     * @return
     */
    private String checkExcelParam(StudentScoreBO studentScoreBO, List<Long> studentNumberList) {
        if (!studentNumberList.contains(studentScoreBO.getStudentNumber())) {
            return "学号不存在!";
        }
        if (null == studentScoreBO.getStudentNumber()) {
            return "学号不能为空!";
        }
        if (null == studentScoreBO.getApplyScore()) {
            return "申请分数不能为空!";
        }
        if (null == studentScoreBO.getFinallyScore()) {
            return "最终分数不能为空!";
        }
        if (null == studentScoreBO.getName()) {
            return "姓名不能为空!";
        }
        if (null == studentScoreBO.getReason()) {
            return "原因不能为空！";
        }
        if (null == studentScoreBO.getRemark()) {
            return "部门不能为空！";
        }
        if (null == studentScoreBO.getPage()) {
            return "页码不能为空！";
        }
        return "验证通过";
    }

    @Override
    public List<StudentScoreBO> getStudentScoreByStudentNumber(String studentScoreTableName, long studentNumber) throws StudentException {
        List<StudentScore> studentScoreList = studentScoreMapper.getStudentScoreByStudentNumber(studentScoreTableName, studentNumber);
        if (studentScoreList != null && studentScoreList.size() > 0) {
            // jdk1.8实现list类型转换
            List<StudentScoreBO> studentScoreBOList =
                    studentScoreList
                            .stream()
                            .map(s -> BeanMapper.map(s, StudentScoreBO.class))
                            .collect(Collectors.toList());
            return studentScoreBOList;
        }
        return null;
    }

    @Override
    public StudentScoreBO getStudentScoreById(String studentScoreTableName, int id) throws StudentException {
        StudentScore studentScore = studentScoreMapper.selectByPrimaryKey(studentScoreTableName, id);
        if (studentScore != null) {
            return BeanMapper.map(studentScore, StudentScoreBO.class);
        }
        return null;
    }

    @Override
    public int updateStudentScore(String studentScoreTableName, StudentScoreBO studentScoreBO) throws StudentException {

        return studentScoreMapper.updateStudentScore(studentScoreTableName, BeanMapper.map(studentScoreBO, StudentScore.class));
    }

    @Override
    public int deleteStudentScore(String studentScoreTableName, int id) throws StudentException {
        StudentScoreBO studentScoreBO = getStudentScoreById(studentScoreTableName, id);
        studentService.updateScoreByStudentNumber(-studentScoreBO.getFinallyScore(), studentScoreBO.getStudentNumber());
        return studentScoreMapper.deleteStudentScore(studentScoreTableName, id);
    }

    @Override
    public int deleteStudentScoreByNumber(String studentScoreTableName, long studentNumber) throws StudentException {
        return studentScoreMapper.deleteStudentScoreByNumber(studentScoreTableName, studentNumber);
    }

    @Override
    public List<StudentScoreBO> getStudentScoreByTime(String studentScoreTableName, Date startTime, Date endTime) throws StudentException {
        List<StudentScore> studentScoreList = studentScoreMapper.getStudentScoreByTime(studentScoreTableName, startTime, endTime);
        if (studentScoreList != null && studentScoreList.size() > 0) {
            // jdk1.8实现list类型转换
            List<StudentScoreBO> studentScoreBOList =
                    studentScoreList
                            .stream()
                            .map(s -> BeanMapper.map(s, StudentScoreBO.class))
                            .collect(Collectors.toList());
            return studentScoreBOList;
        }
        return null;
    }

    @Override
    public List<StudentScoreBO> getStudentScoreByAdmin(String studentScoreTableName, String userName, Date startTime, Date endTime) throws StudentException {
        List<StudentScore> studentScoreList = studentScoreMapper.getStudentScoreByAdmin(studentScoreTableName, userName, startTime, endTime);
        if (studentScoreList != null && studentScoreList.size() > 0) {
            // jdk1.8实现list类型转换
            List<StudentScoreBO> studentScoreBOList =
                    studentScoreList
                            .stream()
                            .map(s -> BeanMapper.map(s, StudentScoreBO.class))
                            .collect(Collectors.toList());
            return studentScoreBOList;
        }
        return null;
    }

    @Override
    public int addStudentScoreTable(String studentScoreTableName) throws StudentException {
        StringBuffer stringBuffer = new StringBuffer(studentScoreTableName);
        int result = 0;
        try {
            result = studentScoreMapper.addStudentScoreTable(studentScoreTableName);
        } catch (Exception e) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.DONOT_REOPERATION_CODE,
                    ResponseCodeConstants.DONOT_REOPERATION_MSG,
                    "");
        }
        return result;
    }

    @Override
    public List<StudentScoreBO> findHistory(String studentScoreTable , long studentNumber) {
        List<StudentScore> historyStudentScoreList = studentScoreMapper.findHistoryStudentScore(studentScoreTable, studentNumber);
        if (historyStudentScoreList != null && historyStudentScoreList.size() > 0) {
            // jdk1.8实现list类型转换
            List<StudentScoreBO> studentScoreBOList =
                    historyStudentScoreList
                            .stream()
                            .map(s -> BeanMapper.map(s, StudentScoreBO.class))
                            .collect(Collectors.toList());
            return studentScoreBOList;
        }
        return null;
    }

    @Override
    public List<String> getStudentScoreTableAll() throws StudentException {
        return studentScoreMapper.getStudentScoreTableAll();
    }


    /**
     * 检查参数
     *
     * @param studentScoreBO
     * @return
     * @throws StudentException
     */
    private void baseParamCheck(StudentScoreBO studentScoreBO, List<Long> studentNumberList) throws StudentException {
        if (!studentNumberList.contains(studentScoreBO.getStudentNumber())) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.STUDENT_NUMBER_NOT_FOUND_FAIL_CODE,
                    ResponseCodeConstants.STUDENT_NUMBER_NOT_FOUND_FAIL_MSG,
                    "");
        }
        if (null == studentScoreBO.getStudentNumber()) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.USERNAME_IS_NOT_NULL_CODE,
                    ResponseCodeConstants.USERNAME_IS_NOT_NULL_MSG,
                    "");
        }
        if (null == studentScoreBO.getApplyScore()) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.APPLYSCORE_IS_NOT_NULL_CODE,
                    ResponseCodeConstants.APPLYSCORE_IS_NOT_NULL_MSG,
                    "");
        }
        if (null == studentScoreBO.getFinallyScore()) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.FINALSCORE_IS_NOT_NULL_CODE,
                    ResponseCodeConstants.FINALSCORE_IS_NOT_NULL_MSG,
                    "");
        }
        if (null == studentScoreBO.getName()) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.STUDENTNAME_IS_NOT_NULL_CODE,
                    ResponseCodeConstants.STUDENTNAME_IS_NOT_NULL_MSG,
                    "");
        }
        if (null == studentScoreBO.getReason()) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.REASON_IS_NOT_NULL_CODE,
                    ResponseCodeConstants.REASON_IS_NOT_NULL_MSG,
                    "");
        }
        if (null == studentScoreBO.getRemark()) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.REMARK_IS_NOT_NULL_CODE,
                    ResponseCodeConstants.REMARK_IS_NOT_NULL_MSG,
                    "");
        }
        if (null == studentScoreBO.getPage()) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.PAGE_IS_NOT_NULL_CODE,
                    ResponseCodeConstants.PAGE_IS_NOT_NULL_MSG,
                    "");
        }
    }
}
